﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace IDotNet.Nssm
{
    public static class NssmServiceManager
    {
        public static TimeSpan ServiceStopTimeout { get; set; }

        private static volatile int RunningThreadCount = 0;

        public static void IncrementRunningThreadCount()
        {
            Debug.WriteLine($"{nameof(IncrementRunningThreadCount)}:{Interlocked.Increment(ref RunningThreadCount)}");
        }
        public static void DecrementRunningThreadCount()
        {
            Debug.WriteLine($"{nameof(DecrementRunningThreadCount)}:{Interlocked.Decrement(ref RunningThreadCount)}");
        }
        static NssmServiceManager()
        {
            ServiceStopTimeout = TimeSpan.FromSeconds(20);
        }

        private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
        {
            Trace.TraceInformation($"Console_CancelKeyPress:{e.SpecialKey.ToString("G")}");
            ServiceStopFuncExecute();
        }

        public static bool RegisterShutdownConsoleEvent()
        {
            Debug.WriteLine($"{nameof(RegisterShutdownConsoleEvent)}");
            Console.CancelKeyPress += Console_CancelKeyPress;
            return true;
        }


        private static void ServiceStopFuncExecute()
        {
            if (ServiceStopHandler == null)
            {
                return;
            }
            var tasks = new List<Task>();
            foreach (var item in ServiceStopHandler.GetInvocationList())
            {
                tasks.Add(((Func<Task>)item)());
            }
            tasks.Add(Task.Run(() =>
            {
                Debug.WriteLine($"Begin check RunningThreadCount:{RunningThreadCount}");
                while (RunningThreadCount > 1)
                {
                    Debug.WriteLine($"RunningThreadCount:{RunningThreadCount}");
                    Thread.Sleep(800);
                }
                Debug.WriteLine($"End check RunningThreadCount:{RunningThreadCount}");
            }));
            var ok = Task.WaitAll(tasks.ToArray(), ServiceStopTimeout);
            Trace.TraceInformation($"ServiceStopHandler result:{ok}");
        }

        public static event Func<Task> ServiceStopHandler;
    }
}
